home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-04 / gs24src.zip / GDEVBGI.C < prev    next >
C/C++ Source or Header  |  1992-02-16  |  11KB  |  367 lines

  1. /* Copyright (C) 1989, 1990, 1991 Aladdin Enterprises.  All rights reserved.
  2.    Distributed by Free Software Foundation, Inc.
  3.  
  4. This file is part of Ghostscript.
  5.  
  6. Ghostscript is distributed in the hope that it will be useful, but
  7. WITHOUT ANY WARRANTY.  No author or distributor accepts responsibility
  8. to anyone for the consequences of using it or for whether it serves any
  9. particular purpose or works at all, unless he says so in writing.  Refer
  10. to the Ghostscript General Public License for full details.
  11.  
  12. Everyone is granted permission to copy, modify and redistribute
  13. Ghostscript, but only under the conditions described in the Ghostscript
  14. General Public License.  A copy of this license is supposed to have been
  15. given to you along with Ghostscript so you can know your rights and
  16. responsibilities.  It should be in a file named COPYING.  Among other
  17. things, the copyright notice and this notice must be preserved on all
  18. copies.  */
  19.  
  20. /* gdevbgi.c */
  21. /* Ghostscript driver for Borland Graphics Interface (BGI) */
  22. #include <string.h>
  23. #include <stdlib.h>
  24. #include <conio.h>
  25. #include <graphics.h>
  26. #include "gx.h"
  27. #include "gxdevice.h"
  28.  
  29. #ifndef BGI_LIB                /* may be set in makefile */
  30. #  define BGI_LIB ""
  31. #endif
  32.  
  33. /*
  34.  * BGI supports these video cards:
  35.  *   Hercules, CGA, MCGA, EGA, VGA, AT&T 400, IBM 8514, PC3270.
  36.  * Highest resolution mode is used with all these video cards.
  37.  * EGA and VGA display 16 colors, the rest are black-and-white only.
  38.  * In addition, the environment variable BGIUSER may be used
  39.  * to define a user-supplied Super VGA driver: see the use.doc file
  40.  * for details.
  41.  */
  42. #define SUPER_VGA 999            /* bogus # for user-defined driver */
  43.  
  44. /* See gxdevice.h for the definitions of the procedures. */
  45.  
  46. dev_proc_open_device(bgi_open);
  47. dev_proc_close_device(bgi_close);
  48. dev_proc_map_rgb_color(bgi_map_rgb_color);
  49. dev_proc_map_color_rgb(bgi_map_color_rgb);
  50. dev_proc_fill_rectangle(bgi_fill_rectangle);
  51. dev_proc_tile_rectangle(bgi_tile_rectangle);
  52. dev_proc_copy_mono(bgi_copy_mono);
  53. dev_proc_copy_color(bgi_copy_color);
  54. dev_proc_draw_line(bgi_draw_line);
  55.  
  56. /* The device descriptor */
  57. typedef struct gx_device_bgi_s gx_device_bgi;
  58. struct gx_device_bgi_s {
  59.     gx_device_common;
  60.     int display_mode;
  61.     struct text_info text_mode;
  62. };
  63. #define bgi_dev ((gx_device_bgi *)dev)
  64. static gx_device_procs bgi_procs = {
  65.     bgi_open,
  66.     gx_default_get_initial_matrix,
  67.     gx_default_sync_output,
  68.     gx_default_output_page,
  69.     bgi_close,
  70.     bgi_map_rgb_color,
  71.     bgi_map_color_rgb,
  72.     bgi_fill_rectangle,
  73.     bgi_tile_rectangle,
  74.     bgi_copy_mono,
  75.     bgi_copy_color,
  76.     bgi_draw_line,
  77.     gx_default_get_bits,
  78.     gx_default_get_props,
  79.     gx_default_put_props
  80. };
  81. gx_device_bgi gs_bgi_device = {
  82.     sizeof(gx_device_bgi),
  83.     &bgi_procs,
  84.     "bgi",
  85.     0, 0,        /* width and height are set in bgi_open */
  86.     0, 0,        /* density is set in bgi_open */
  87.     no_margins,
  88.     dci_black_and_white,
  89.     0        /* not open yet */
  90. };
  91.  
  92. /* Detection procedure for user-defined driver. */
  93. private int huge
  94. detectVGA()
  95. {    return gs_bgi_device.display_mode;
  96. }
  97.  
  98. /* Open the BGI driver for graphics mode */
  99. int
  100. bgi_open(gx_device *dev)
  101. {    int driver, mode;
  102.     char *bgi_user = getenv("BGIUSER");
  103.     char *bgi_path = getenv("BGIPATH");
  104.  
  105.     gettextinfo(&bgi_dev->text_mode);
  106.  
  107.     if ( bgi_path == NULL )
  108.         bgi_path = BGI_LIB;
  109.     if ( bgi_user != NULL )
  110.        {    /* A user-supplied driver is specified as "mode.dname", */
  111.         /* where mode is a hex number and dname is the name */
  112.         /* of the driver file. */
  113.         char dname[40];
  114.         if ( strlen(bgi_user) > sizeof(dname) ||
  115.              sscanf(bgi_user, "%x.%s", &mode, dname) != 2
  116.            )
  117.            {    eprintf("BGIUSER not in form nn.dname.\n");
  118.             exit(1);
  119.            }
  120.         gs_bgi_device.display_mode = mode;    /* sigh.... */
  121.         installuserdriver(dname, detectVGA);
  122.         driver = DETECT;
  123.         initgraph(&driver, &mode, bgi_path);
  124.         driver = SUPER_VGA;
  125.        }
  126.     else                /* not user-defined driver */
  127.        {    /* We include the CGA and Hercules drivers */
  128.         /* in the Ghostscript executable, so end-users don't */
  129.         /* have to have the BGI files. */
  130.         if ( registerbgidriver(CGA_driver) < 0 )
  131.            {    eprintf("BGI: Can't register CGA driver!\n");
  132.             exit(1);
  133.            }
  134.         if ( registerbgidriver(Herc_driver) < 0 )
  135.            {    eprintf("BGI: Can't register Hercules driver!\n");
  136.             exit(1);
  137.            }
  138.  
  139.         detectgraph(&driver, &mode);
  140.         if ( driver < 0 )
  141.            {    eprintf("BGI: No graphics hardware detected!\n");
  142.             exit(1);
  143.            }
  144.  
  145.         if ( driver == EGA64 )
  146.            {    /* Select 16 color video mode if video card is EGA with 64 Kb of memory */
  147.             mode = EGA64LO;
  148.            }
  149.  
  150.         /* Initialize graphics mode. */
  151.  
  152.         /* Following patch for AT&T 6300 is courtesy of */
  153.         /* Allan Wax, Xerox Corp. */
  154.         if ( driver == CGA )
  155.            {    /* The actual hardware might be an AT&T 6300. */
  156.             /* Try initializing it that way. */
  157.             int save_mode = mode;
  158.             driver = ATT400, mode = ATT400HI;
  159.             initgraph(&driver, &mode, bgi_path);
  160.             if ( graphresult() != grOk )
  161.                {    /* Nope, it was a real CGA. */
  162.                 closegraph();
  163.                 driver = CGA, mode = save_mode;
  164.                 initgraph(&driver, &mode, bgi_path);
  165.                }
  166.            }
  167.         else
  168.             initgraph(&driver, &mode, bgi_path);
  169.        }
  170.  
  171.        {    int code = graphresult();
  172.         if ( code != grOk )
  173.            {    eprintf1("Error initializing BGI driver: %s\n",
  174.                  grapherrormsg(code));
  175.             exit(1);
  176.            }
  177.        }
  178.  
  179.     /* Set parameters that were unknown before opening device */
  180.  
  181.     /* Size and nominal density of screen. */
  182.     /* The following algorithm maps an appropriate fraction of */
  183.     /* the display screen to an 8.5" x 11" coordinate space. */
  184.     /* This may or may not be what is desired! */
  185.     dev->width = getmaxx() + 1;
  186.     dev->height = getmaxy() + 1;
  187.     dev->y_pixels_per_inch = dev->height / 11.0;
  188.        {    /* Get the aspect ratio from the driver. */
  189.         int arx, ary;
  190.         getaspectratio(&arx, &ary);
  191.         dev->x_pixels_per_inch =
  192.             dev->y_pixels_per_inch * ((float)ary / arx);
  193.        }
  194.  
  195.     /* Find out if the device supports color */
  196.     /* (default initialization is monochrome). */
  197.     /* We only recognize 16-color devices right now. */
  198.     if ( getmaxcolor() > 1 )
  199.        {    static gx_device_color_info bgi_16color = dci_color(4, 2, 3);
  200.         dev->color_info = bgi_16color;
  201.        }
  202.     return 0;
  203. }
  204.  
  205. /* Close the BGI driver */
  206. int
  207. bgi_close(gx_device *dev)
  208. {    closegraph();
  209.     textmode(bgi_dev->text_mode.currmode);
  210.     return 0;
  211. }
  212.  
  213. /* Map a r-g-b color to the 16 colors available with an EGA/VGA video card. */
  214. gx_color_index
  215. bgi_map_rgb_color(gx_device *dev, gx_color_value r, gx_color_value g,
  216.   gx_color_value b)
  217. {    return (gx_color_index)
  218.         ((r > gx_max_color_value / 4 ? 4 : 0) +
  219.          (g > gx_max_color_value / 4 ? 2 : 0) +
  220.          (b > gx_max_color_value / 4 ? 1 : 0) +
  221.          (r > gx_max_color_value / 4 * 3 ||
  222.           g > gx_max_color_value / 4 * 3 ? 8 : 0));
  223. }
  224.  
  225. /* Map a color code to r-g-b.  Surprisingly enough, this is algorithmic. */
  226. int
  227. bgi_map_color_rgb(gx_device *dev, gx_color_index color,
  228.   gx_color_value prgb[3])
  229. {
  230. #define icolor (int)color
  231.     gx_color_value one =
  232.         (icolor & 8 ? gx_max_color_value : gx_max_color_value / 3);
  233.     prgb[0] = (icolor & 4 ? one : 0);
  234.     prgb[1] = (icolor & 2 ? one : 0);
  235.     prgb[2] = (icolor & 1 ? one : 0);
  236.     return 0;
  237. #undef icolor
  238. }
  239.  
  240. /* Copy a monochrome bitmap.  The colors are given explicitly. */
  241. /* Color = gx_no_color_index means transparent (no effect on the image). */
  242. int
  243. bgi_copy_mono(gx_device *dev,
  244.   byte *base, int sourcex, int raster, gx_bitmap_id id,
  245.   int x, int y, int w, int h,
  246.   gx_color_index zero, gx_color_index one)
  247. {    byte *ptr_line = base + (sourcex >> 3);
  248.     int left_bit = 0x80 >> (sourcex & 7);
  249.     int dest_y = y, end_x = x + w;
  250.     int invert = 0;
  251.     int color;
  252.  
  253.     if ( zero == gx_no_color_index )
  254.        {    if ( one == gx_no_color_index ) return 0;
  255.         color = (int)one;
  256.        }
  257.     else
  258.        {    if ( one == gx_no_color_index )
  259.            {    color = (int)zero;
  260.             invert = -1;
  261.            }
  262.         else
  263.            {    /* Pre-clear the rectangle to zero */
  264.             setfillstyle(SOLID_FILL, (int)zero);
  265.             bar(x, y, x + w - 1, y + h - 1);
  266.             color = (int)one;
  267.            }
  268.        }
  269.  
  270.     while ( h-- )              /* for each line */
  271.        {    byte *ptr_source = ptr_line;
  272.         register int dest_x = x;
  273.         register int bit = left_bit;
  274.         while ( dest_x < end_x )     /* for each bit in the line */
  275.            {    if ( (*ptr_source ^ invert) & bit )
  276.                 putpixel(dest_x, dest_y, color);
  277.             dest_x++;
  278.             if ( (bit >>= 1) == 0 )
  279.                 bit = 0x80, ptr_source++;
  280.            }
  281.         dest_y++;
  282.         ptr_line += raster;
  283.        }
  284.     return 0;
  285. }
  286.  
  287.  
  288. /* Copy a color pixel map.  This is just like a bitmap, except that */
  289. /* each pixel takes 4 bits instead of 1 when device driver has color. */
  290. int
  291. bgi_copy_color(gx_device *dev,
  292.   byte *base, int sourcex, int raster, gx_bitmap_id id,
  293.   int x, int y, int w, int h)
  294. {    if ( gx_device_has_color(dev) )
  295.        {    /* color device, four bits per pixel */
  296.         byte *line = base + (sourcex >> 1);
  297.         int dest_y = y, end_x = x + w;
  298.  
  299.         if ( w <= 0 ) return 0;
  300.         while ( h-- )              /* for each line */
  301.            {    byte *source = line;
  302.             register int dest_x = x;
  303.             if ( sourcex & 1 )    /* odd nibble first */
  304.                {    int color =  *source++ & 0xf;
  305.                 putpixel(dest_x, dest_y, color);
  306.                 dest_x++;
  307.                }
  308.             /* Now do full bytes */
  309.             while ( dest_x < end_x )
  310.                {    int color = *source >> 4;
  311.                 putpixel(dest_x, dest_y, color);
  312.                 dest_x++;
  313.                 if ( dest_x < end_x )
  314.                    {    color =  *source++ & 0xf;
  315.                     putpixel(dest_x, dest_y, color);
  316.                     dest_x++;
  317.                    }
  318.                }
  319.             dest_y++;
  320.             line += raster;
  321.            }
  322.        }
  323.     else /* monochrome device: one bit per pixel */
  324.        {    /* bitmap is the same as bgi_copy_mono: one bit per pixel */
  325.         bgi_copy_mono(dev, base, sourcex, raster, id, x, y, w, h,
  326.             (gx_color_index)BLACK, (gx_color_index)WHITE);
  327.        }
  328.     return 0;
  329. }
  330.  
  331.  
  332. /* Fill a rectangle. */
  333. int
  334. bgi_fill_rectangle(gx_device *dev, int x, int y, int w, int h,
  335.   gx_color_index color)
  336. {    setfillstyle(SOLID_FILL, (int)color);
  337.     bar(x, y, x + w - 1, y + h - 1);
  338.     return 0;
  339. }
  340.  
  341.  
  342. /* Tile a rectangle.  If neither color is transparent, */
  343. /* pre-clear the rectangle to color0 and just tile with color1. */
  344. /* This is faster because of how bgi_copy_mono is implemented. */
  345. /* Note that this also does the right thing for colored tiles. */
  346. int
  347. bgi_tile_rectangle(gx_device *dev, gx_bitmap *tile,
  348.   int x, int y, int w, int h, gx_color_index czero, gx_color_index cone,
  349.   int px, int py)
  350. {    if ( czero != gx_no_color_index && cone != gx_no_color_index )
  351.        {    bgi_fill_rectangle(dev, x, y, w, h, czero);
  352.         czero = gx_no_color_index;
  353.        }
  354.     return gx_default_tile_rectangle(dev, tile, x, y, w, h, czero, cone, px, py);
  355. }
  356.  
  357.  
  358. /* Draw a line */
  359. int
  360. bgi_draw_line(gx_device *dev, int x0, int y0, int x1, int y1,
  361.   gx_color_index color)
  362. {    setcolor((int)color);
  363.     setlinestyle(SOLID_LINE, 0, NORM_WIDTH);  /* solid, one pixel wide */
  364.     line(x0, y0, x1, y1);
  365.     return 0;
  366. }
  367.